/*
 Copyright (c) 2013 MeherTJ G. All rights reserved.
 License: LGPL for personnal study or free software.
*/

#pragma once

/**
		Brief:
		-- function:
		LogE(fmt, ...)
		LogD(fmt, ...)
		LogI(fmt, ...)
*/

#include <cstdarg>
#include <cstdio>
#include <ctime>
#include <sstream>

#include "zen_macro.h"

#ifdef ZEN_OS_ANDROID
#include "android/log.h"
#endif

namespace Zen
{
    enum class ELogType
    {
        Verbose,
        Debug,
        Info,
        Error,
    };
    inline void __LogPrint(ELogType type, char const* fmt, va_list args)
    {
#ifdef ZEN_OS_ANDROID
        auto at = ANDROID_LOG_ERROR;
        if (type == ELogType::Debug)
            at = ANDROID_LOG_DEBUG;
        else if (type == ELogType::Info)
            at = ANDROID_LOG_INFO;
        __android_log_vprint(at, "ZEN_LOG", fmt, args);
#else
        std::string fmts;
        char at = 'E';
        if (type == ELogType::Debug)
            at = 'D';
        else if (type == ELogType::Info)
            at = 'I';
        else if (type == ELogType::Verbose)
            at = 'V';
        fmts.push_back(at);
        fmts.push_back(':');
        fmts.append(fmt);
        fmts.append("\n");
        vfprintf((type == ELogType::Error ? stderr : stdout), fmts.c_str(), args);
        fflush(stdout);
#endif
    }

    // log error
    inline void LogE(char const* fmt, ...)
    {
        va_list va;
        va_start(va, fmt);
        __LogPrint(ELogType::Error, fmt, va);
        va_end(va);
    }

    inline void LogV(char const* fmt, ...)
    {
        va_list va;
        va_start(va, fmt);
        __LogPrint(ELogType::Verbose, fmt, va);
        va_end(va);
    }

    inline void LogI(char const* fmt, ...)
    {
        va_list va;
        va_start(va, fmt);
        __LogPrint(ELogType::Info, fmt, va);
        va_end(va);
    }

    // log debug info
    inline void LogD(char const* fmt, ...)
    {
        va_list va;
        va_start(va, fmt);
        __LogPrint(ELogType::Debug, fmt, va);
        va_end(va);
    }

    inline char const* PickFileName(char const* filename)
    {
        for (auto it = filename; *it != 0; ++it)
        {
            if (*it == '/' || *it == '\\') filename = it + 1;
        }
        return filename;
    }
} // namespace Zen

#define __FILENAME__ Zen::PickFileName(__FILE__)

inline const char* __S(std::string const& s)
{
    return s.c_str();
}
inline const char* __S(const char* s)
{
    return s;
}

#define __Trace(value) Zen::LogD("[%d]@%s#%d$%s", (int)value, __FILENAME__, __LINE__, __FUNCTION__)
#define __TraceString(msg) Zen::LogD("%s@%s#%d$%s", __S(msg), __FILENAME__, __LINE__, __FUNCTION__)
